Skip to main content

编写 Go 项目的 Makefile 不完全指南

Makefile 的主要的作用是简化构建难度,以及减少 “祖传” 代码。

=====================================

我也看了很多关于 Go 的 Makefile 文章,但是大部分都是如何用,以及贴上一个特别简单的例子,想要放到 实际项目中使用还相差的很远,所以决定自己写一份自认为可以覆盖 Go 项目的大部分场景的 Makefile 通用 模版。

覆盖了以下场景:

  • 多程序编译
  • 交叉编译
  • 基于 docker 编译
  • 基于 pakcage 的覆盖率单元测试
  • 清理编译环境

模版

既然是模版所以肯定会涉及到参数的修改,模版中可以修改的变量都为大写字母,意思也很明确这里就不多介绍了。

VERSION ?= v1.0.0
BUILD_DIR ?= build

PKG_NAME = github.com/yakumioto/go-makefile-example
IMAGE_NAME = yakumioto/go-makefile-example-

CGO_ENABLED ?= $(shell go env CGO\_ENABLED)
GOARCH ?= $(shell go env GOARCH)
GOOS ?= $(shell go env GOOS)
GO_LDFLAGS ?= -s -w -extldflags \"-static\\" override timestamp = $(shell date '+%s') override app = $(filter-out $@,$(MAKECMDGOALS)) override package = $(PKG\_NAME)/$(filter-out $@,$(MAKECMDGOALS)) override output\_build\_dir = $(BUILD\_DIR)/apps/$(GOOS) override output\_test\_dir = $(BUILD\_DIR)/tests .PHONY : build docker-build test clean %: @: build: @echo "Building $(app) app..." @mkdir -p $(output\_build\_dir) CGO\_ENABLED=$(CGO\_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $(output\_build\_dir)/$(app) -ldflags '$(GO\_LDFLAGS)' $(PKG\_NAME)/cmd/$(app) docker-build: @echo "Building $(app) app in docker..." @echo "Building vendor..." @go mod vendor @echo "Building image..." @docker build \\ --build-arg command="CGO_ENABLED=$(CGO\_ENABLED) go build -o /app -ldflags '$(GO\_LDFLAGS)' $(PKG\_NAME)/cmd/$(app)" \\ -t $(IMAGE\_NAME)$(app):$(VERSION) -f images/$(app)/Dockerfile . test: @echo "Testing $(package) ..." @mkdir -p $(output\_test\_dir) go test -coverprofile=$(output\_test\_dir)/$(timestamp).out $(package) clean: @echo "Cleaning..." @rm -rf build/\* @rm -rf vendor 复制代码

使用

github.com/yakumioto/m… 为例,系统为 macOS

makefile-go-eample
├── build
├── cmd
│   └── add
├── images
│   └── add
└── internal
└── utils
复制代码

命令栗子:

  • make build add
  • make docker-build add
  • make build add GOOS=linux
  • make docker-build add GOOS=linux GOARCH=386
  • make test internal/utils
  • make clean

当然很多命令都可以追加参数,以达到想要的目的,不过我觉得已经覆盖大部分场景了。